package org.example.new_hbps_backend_reconstruction.controller.patient;

import com.alibaba.fastjson2.JSONObject;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.new_hbps_backend_reconstruction.common.results.R;
import org.example.new_hbps_backend_reconstruction.dto.PatientSessionDTO;
import org.example.new_hbps_backend_reconstruction.entity.PatientBaseEntity;
import org.example.new_hbps_backend_reconstruction.entity.request.BindPhoneNumberRequest;
import org.example.new_hbps_backend_reconstruction.service.PatientLoginService;
import org.example.new_hbps_backend_reconstruction.utils.UserHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

/**
 * @author 丁利军
 * @date 2025年10月09日 21:42
 * @description 患者登录
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/patient/patientLogin")
@Tag(name = "患者用户登录管理", description = "提供患者用户获取 openId、登录、获取/绑定手机号、变更绑定等接口")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
@Slf4j
public class PatientLoginController {

    private final RestTemplate restTemplate;

    @Autowired
    private PatientLoginService patientLoginService;

    @Operation(
            summary = "获取微信 OpenID",
            description = "根据前端传入的临时登录凭证 code，调用微信接口换取 openId。"
    )
    @Parameter(
            name = "code",
            description = "微信小程序/公众号登录临时 code",
            required = true
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/get_wx_open_id/{code}")
    public R getWxOpenId(@PathVariable String code) {
        // 获取微信的 openId
        log.info("获取微信的 openId");
        R r = patientLoginService.getWxOpenId(code);
        return r;
    }

    @Operation(
            summary = "获取当前登录用户的信息",
            description = "获取当前登录用户的信息，暂时用于测试登录校验逻辑，拦截器等是否正常"
    )

    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @GetMapping("/get_user_self")
    public R getUserSelf() {
        PatientSessionDTO dto= UserHolder.getUser();
        return R.ok(dto);
    }


    @Operation(
            summary = "自定义登录",
            description = "根据 openId 进行账号登录或注册。"
    )
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
            required = true,
            description = "包含 openId 的 JSON 对象，如：{\"openId\": \"wx_xxx\"}",
            content = @Content(schema = @Schema(implementation = JSONObject.class))
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "登录成功"),
            @ApiResponse(responseCode = "400", description = "传入 openId 为空"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping("/custom_login")
    public R customLogin(@RequestBody JSONObject jsonObject) {
        String openId = jsonObject.getString("openId");
        if (openId.isBlank()) {
            return R.failed("传入openid为空");
        }
        // 自定义的登录服务
        R r = patientLoginService.customLogin(openId);
        return r;
    }

    @Operation(
            summary = "获取手机号码",
            description = "使用微信提供的手机号 code 解密并返回手机号码。"
    )
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
            required = true,
            description = "包含手机号凭证 code 的请求体",
            content = @Content(schema = @Schema(implementation = BindPhoneNumberRequest.class))
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "获取成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误或 code 无效"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping("/get_phone_number")
    public R getPhoneNumber(@RequestBody BindPhoneNumberRequest bindPhoneNumberRequest) {
        // 获取手机号码
        String code = bindPhoneNumberRequest.getPhoneCode();
        R r = patientLoginService.getPhoneNumber(code);
        return r;
    }

    @Operation(
            summary = "绑定手机号码",
            description = "将当前登录用户与手机号码进行绑定。"
    )
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
            required = true,
            description = "包含手机号、验证码/凭证等信息的请求体",
            content = @Content(schema = @Schema(implementation = BindPhoneNumberRequest.class))
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "绑定成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "409", description = "该手机号已被绑定"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping("/bind_phone_number")
    public R bindPhoneNumber(@RequestBody BindPhoneNumberRequest bindPhoneNumberRequest) {
        // 绑定手机号码
        R r = patientLoginService.bindPhoneNumber(bindPhoneNumberRequest);
        return r;
    }

    @Operation(
            summary = "通用测试接口",
            description = "用于测试 service 层通用登录/校验流程（pigLogin）。"
    )
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
            required = true,
            description = "患者基本实体对象",
            content = @Content(schema = @Schema(implementation = PatientBaseEntity.class))
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "测试调用成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping("/normal_test")
    public R normal_test(@RequestBody PatientBaseEntity one) {
        // 通用的测试 service 服务的接口
        R r = patientLoginService.pigLogin(one);
        return r;
    }

    @Operation(
            summary = "更换绑定手机号",
            description = "对已绑定手机号进行更换，通常需要进行校验后完成替换。"
    )
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
            required = true,
            description = "包含用于更换绑定手机号的必要信息",
            content = @Content(schema = @Schema(implementation = BindPhoneNumberRequest.class))
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "更换成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误"),
            @ApiResponse(responseCode = "401", description = "未授权或未登录"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping("/change_bind_phone_number")
    public R changeBindPhoneNumber(@RequestBody BindPhoneNumberRequest bindPhoneNumberRequest) {
        return patientLoginService.changeBindPhoneNumber(bindPhoneNumberRequest);
    }

    @Operation(
            summary = "手机号密码登录",
            description = "使用手机号和密码进行登录，密码默认为手机号。"
    )
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
            required = true,
            description = "包含手机号和密码的 JSON 对象，如：{\"phoneNumber\": \"13800138000\", \"password\": \"13800138000\"}",
            content = @Content(schema = @Schema(implementation = com.alibaba.fastjson.JSONObject.class))
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "登录成功"),
            @ApiResponse(responseCode = "400", description = "手机号或密码为空"),
            @ApiResponse(responseCode = "401", description = "手机号或密码错误"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping("/phone_login")
    public R phoneLogin(@RequestBody com.alibaba.fastjson.JSONObject jsonObject) {
        log.info("收到手机号登录请求, body={}", jsonObject);

        String phoneNumber = jsonObject.getString("phoneNumber");
        String password = jsonObject.getString("password");

        if (phoneNumber == null || phoneNumber.isBlank()) {
            log.warn("手机号为空");
            return R.failed("手机号为空");
        }
        if (password == null || password.isBlank()) {
            log.warn("密码为空");
            return R.failed("密码为空");
        }

        R r = patientLoginService.phoneLogin(phoneNumber, password);
        log.info("手机号登录响应, code={}, msg={}", r.getCode(), r.getMsg());
        return r;
    }
}
